package server

import (
	"bytes"
	"cgs-server/helper"
	"context"
	"go.mongodb.org/mongo-driver/bson"
	"io/ioutil"
	"net/http"
	"strings"
)

func SdkMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {

	auth, ok := apiAuthorities2[r.URL.Path]
	if !ok {
		// path is not registered.
		Logger.Errorf("%v is not registered", r.URL.Path)
		writeNotAllowed(w)
		return
	}
	isApi := strings.HasPrefix(auth.ApiPath, "/api/v1") || strings.HasPrefix(auth.ApiPath, "/api/v2")
	// api needs no authority
	if auth.Auth == string(None) && isApi {
		appKey := ""
		sign := ""
		if len(r.Header) > 0 {
			for k, v := range r.Header {
				if k == "App-Key" {
					appKey = v[0]
				} else if k == "Sign" {
					sign = v[0]
				}
			}
		}
		if appKey == "" || sign == "" {
			r.ParseForm()
			appKey = r.FormValue("App-Key")
			sign = r.FormValue("Sign")
		}
		// 从 body 里读取
		if appKey == "" || sign == "" {
			result := struct {
				AppKey string `json:"App-Key"`
				Sign   string
			}{}
			bodyBytes, _ := ioutil.ReadAll(r.Body)
			r.Body.Close() //  must close
			_ = helper.FromJSON(bodyBytes, &result)
			appKey = result.AppKey
			sign = result.Sign
			r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
		}
		if appKey == "" || sign == "" {
			helper.WriteJSON(w, Result{
				Code: 300,
				Msg:  "AppKey or Sign is missing.",
			})
			return
		}
		db, err := Mongo()
		if err != nil {
			helper.WriteJSON(w, Result{
				Code: 300,
				Msg:  err.Error(),
			})
			return
		}
		filter := bson.M{
			"AppKey": appKey,
		}
		doc := bson.M{}
		find, _ := db.FindOne(CgsAppKeyCollectionName, filter, &doc)
		if !find {
			helper.WriteJSON(w, Result{
				Code: 300,
				Msg:  "Can not find AppKey  " + appKey,
			})
			return
		} else {
			appSecret := doc["AppSecret"].(string)
			timestamp := doc["Timestamp"].(string)
			authType := doc["AuthType"].(string)
			if authType == "0" {
				// 密钥未启用
				_, _ = helper.WriteJSON(w, Fail("AppKey is not enabled"))
				return
			}

			signs := helper.EncryptBase62(appKey + "&" + appSecret + "&" + timestamp)
			sign = strings.TrimSpace(sign)
			if signs != sign {
				helper.WriteJSON(w, Result{
					Code: 300,
					Msg:  "AppKey  Not Valid",
				})
				return
			}
			userID := doc["UserID"]
			ctx := context.WithValue(context.Background(), "userID", userID)
			ctx = context.WithValue(ctx, "authType", authType)
			r = r.WithContext(ctx)
			next(w, r)
			return
		}

	}

	next.ServeHTTP(w, r)

}
